#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <sys/poll.h>
#include <sys/epoll.h>

#include "common.h"

int InitBlockInfoBuffer(BlockInfo *pBlockInfo,int nInfoSize,int nDataSize,unsigned char *pBuf,int nBufCount)
{
		pthread_mutexattr_t mattr;
	
		if( pthread_mutexattr_init(&mattr) != 0 ) 
				printf("pthread_mutexattr_init failure {%s(%d)}\n",__FILE__,__LINE__);					
		if( pthread_mutexattr_setpshared(&mattr,PTHREAD_PROCESS_SHARED) != 0  ) 
				printf("pthread_mutexattr_init failure {%s(%d)}\n",__FILE__,__LINE__);		
	
		if( sem_init(&(pBlockInfo->m_Semaphore), 1, 0) != 0 ) 
		{
				printf("sem_init failure {%s(%d)}\n",__FILE__,__LINE__);	
				return -1;	
		}	
		
		if( pthread_mutex_init (&pBlockInfo->m_Lock,&mattr) != 0 ) 
		{
				printf("pthread_mutex_init failure {%s(%d)}\n",__FILE__,__LINE__);	
				return -1;	
		}	
		
		if( pBuf != NULL )
		{
				pBlockInfo->m_pInfo = (BufferInfo*)pBuf;
				
				if( int( nInfoSize*sizeof(BufferInfo)+nDataSize ) > nBufCount )
				{
						printf("( nInfoSize*sizeof(BufferInfo)+nDataSize ) > nBufCount {%s(%d)}\n",__FILE__,__LINE__);	
						return -1;	
				}						
		}
		else if( ( pBlockInfo->m_pInfo = (BufferInfo*)malloc(nInfoSize*sizeof(BufferInfo)+nDataSize) ) == NULL ) 
		{
				printf("sem_init failure {%s(%d)}\n",__FILE__,__LINE__);	
				return -1;	
		}	
						
		pBlockInfo->m_nInfoSize = nInfoSize;
		pBlockInfo->m_nDataSize = nDataSize;
		pBlockInfo->m_pData = (unsigned char *)(pBlockInfo->m_pInfo+pBlockInfo->m_nInfoSize);
		
		pBlockInfo->m_Push = pBlockInfo->m_Pop = pBlockInfo->m_pInfo;
		pBlockInfo->m_pCurr = pBlockInfo->m_pData;
		
		BufferInfo *pTempBufInfo  = pBlockInfo->m_pInfo;	
			
		for( int i = 0; i < pBlockInfo->m_nInfoSize; i++ )
		{																
				if( i == ( pBlockInfo->m_nInfoSize - 1 ) )
					pTempBufInfo->pNext	= pBlockInfo->m_pInfo;
				else
					pTempBufInfo->pNext	= pTempBufInfo + 1;	
				
				pTempBufInfo ++;	
		}		
		
		return 0;	
}

int PushBlockInfoData(BlockInfo *pBlockInfo,unsigned char *pData,int iSize, unsigned char *pFrontData, int iFrontSize)
{
		int ret = 0;
		BufferInfo *Pop;	
	
		pthread_mutex_lock (&(pBlockInfo->m_Lock));	
	
		if( iSize > pBlockInfo->m_nDataSize )
		{	
			 	ret = -1;
				pthread_mutex_unlock (&(pBlockInfo->m_Lock));					
				return ret;				 	
		}	 	 

		if( pBlockInfo->m_Push->nFlag != 0  ) 
		{  	
				ret = -2;	 
				pthread_mutex_unlock (&(pBlockInfo->m_Lock));					
				return ret;			
		}

		if( iSize > ( pBlockInfo->m_pData + pBlockInfo->m_nDataSize - pBlockInfo->m_pCurr ) ) 
		{	
				pBlockInfo->m_pCurr = pBlockInfo->m_pData;
		}
				
		Pop = pBlockInfo->m_Pop;
		
	 	while( Pop->nFlag )
		{						
				if( Pop->pData >= pBlockInfo->m_pCurr )
				{
						if ( ( Pop->pData - pBlockInfo->m_pCurr ) < iSize )		
						{  	
								ret = -3;	 
								pthread_mutex_unlock (&(pBlockInfo->m_Lock));					
								return ret;			
						}
							
				}			
				Pop = Pop->pNext;
		}		


		//memcpy(pBlockInfo->m_pCurr,pData,iSize);	
		
		if(pFrontData != NULL && iFrontSize > 0)
		{
				memcpy(pBlockInfo->m_pCurr, pFrontData, iFrontSize);
				memcpy(pBlockInfo->m_pCurr + iFrontSize, pData, iSize);
		}
		else
		{
				memcpy(pBlockInfo->m_pCurr,pData,iSize);
		}
			
		pBlockInfo->m_Push->pData = pBlockInfo->m_pCurr;
		pBlockInfo->m_Push->nSize = iSize;	
		pBlockInfo->m_Push->nFlag = 1;		
		pBlockInfo->m_Push = pBlockInfo->m_Push->pNext;
		
		pBlockInfo->m_pCurr += iSize;
		
		sem_post(&(pBlockInfo->m_Semaphore));	
			
		pthread_mutex_unlock (&(pBlockInfo->m_Lock));		
			
		return ret;
}

int GetCode(unsigned char *src,int count,unsigned char **pOut,int *iSize)
{
		unsigned char *pTmp = NULL;
		int  start=0,i=0,size;
		
		*pOut = NULL;
		*iSize = 0;
	
		for( i = 0; i <= ( count - 4 ); i++ )	
		{
				if( src[i] == 0 && src[i+1] == 0 && src[i+2] == 1 )	
				{
						if( pTmp )
						{
								size  = i - start;																	
								if( i > 0 ) if( src[i-1] == 0 )  size--;										
								*pOut = pTmp;
								*iSize = size;
								return 1;		
						}		
										
						start = i + 3;
						pTmp  = src + i + 3;	
							
				}
		}						

		size = 0;
		
		if( pTmp != NULL )
		{
				size = src + count - pTmp;
		}
		
		if( size > 0 )
		{
				*pOut = pTmp;
				*iSize = size;
				return 0;			
		}	
		
		return -1;

}
